package cn.js.sangu.unitStore.controller;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import org.springframework.beans.BeanUtils;
import cn.js.sangu.unitStore.common.R;
import cn.js.sangu.unitStore.dto.DictionariesDTO;
import cn.js.sangu.unitStore.entity.DicDz;
import cn.js.sangu.unitStore.entity.Dictionaries;
import cn.js.sangu.unitStore.service.UserService;
import cn.js.sangu.unitStore.utils.TokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;

import cn.hutool.core.util.StrUtil;
import cn.js.sangu.unitStore.common.LogType;
import cn.js.sangu.unitStore.common.MyLogsAOP;
import cn.js.sangu.unitStore.common.R;
import cn.js.sangu.unitStore.dto.DictionariesDTO;
import cn.js.sangu.unitStore.entity.Dictionaries;
import cn.js.sangu.unitStore.entity.User;
import cn.js.sangu.unitStore.service.DicCzService;
import cn.js.sangu.unitStore.service.DicDzService;
import cn.js.sangu.unitStore.service.DicGgService;
import cn.js.sangu.unitStore.service.DictionariesService;
import cn.js.sangu.unitStore.service.UserService;
import cn.js.sangu.unitStore.utils.TokenUtils;
import lombok.extern.slf4j.Slf4j;

/**
 * 说明：字典记录接口
 * 作者：linshuo
 * 日期：2024/8/7 8:40
 */
// @CrossOrigin //已有全局跨域设置CorsConfig
@RequestMapping("dictionaries")
@RestController
@Slf4j
public class DictionariesController {

    static final String OPERATION_DICTIONARIES = "字典记录";

    @Autowired
    UserService userService;

    /**
     * 字典类型枚举，定义系统支持的字典分类
     */
    public enum DictionaryType {
        /** 定制标准件类型 */
        DZ("dz"),
        /** 材质类型 */
        CZ("cz"),
        /** 规格类型 */
        GG("gg");

        private final String code;
        private static final Map<String, DictionaryType> CODE_MAP;

        static {
            Map<String, DictionaryType> tempMap = new HashMap<>();
            for (DictionaryType type : values()) {
                tempMap.put(type.code, type);
            }
            CODE_MAP = Collections.unmodifiableMap(tempMap);
        }

        DictionaryType(String code) {
            this.code = code;
        }

        /**
         * 根据编码获取对应的字典类型枚举
         * 
         * @param code 类型编码（允许空/空白字符串）
         * @return 匹配的枚举实例，无匹配时返回null
         */
        public static DictionaryType of(String code) {
            return StrUtil.isBlank(code) ? null : CODE_MAP.get(code.trim());
        }
    }

    @Autowired
    private DictionariesService dictionariesService;

    @Autowired
    private DicDzService dicDzService;

    @Autowired
    private DicCzService dicCzService;

    @Autowired
    private DicGgService dicGgService;

    /**
     * 根据类型查询字典列表
     */
    @GetMapping("findByPage")
    @MyLogsAOP(operation = OPERATION_DICTIONARIES, operaType = LogType.LOOKUP)
    public R findByPage(
            @RequestParam() String type,
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize,
            @RequestParam(defaultValue = "") String searchName,
            @RequestParam(defaultValue = "") String searchCode,
            @RequestParam(defaultValue = "id") String sortField,
            @RequestParam(defaultValue = "asc") String sortOrder) {
        IPage<Dictionaries> resultPage = new Page<>(pageNum, pageSize);
        IService<?> service = getServiceByType(type);
        LambdaQueryWrapper<Dictionaries> queryWrapper = Wrappers.lambdaQuery();
        if (!searchName.isEmpty())
            queryWrapper.like(Dictionaries::getName, searchName);
        if (!searchCode.isEmpty())
            queryWrapper.like(Dictionaries::getCode, searchCode);

        // 根据前端传递的排序参数进行动态排序
        if (sortField != null && !sortField.isEmpty()) {
            switch (sortField) {
                case "id":
                    if ("asc".equalsIgnoreCase(sortOrder)) {
                        queryWrapper.orderByAsc(Dictionaries::getId);
                    } else {
                        queryWrapper.orderByDesc(Dictionaries::getId);
                    }
                    break;
                case "name":
                    if ("asc".equalsIgnoreCase(sortOrder)) {
                        queryWrapper.orderByAsc(Dictionaries::getName);
                    } else {
                        queryWrapper.orderByDesc(Dictionaries::getName);
                    }
                    break;
                case "code":
                    if ("asc".equalsIgnoreCase(sortOrder)) {
                        queryWrapper.orderByAsc(Dictionaries::getCode);
                    } else {
                        queryWrapper.orderByDesc(Dictionaries::getCode);
                    }
                    break;
                case "creatTime":
                    if ("asc".equalsIgnoreCase(sortOrder)) {
                        queryWrapper.orderByAsc(Dictionaries::getCreatTime);
                    } else {
                        queryWrapper.orderByDesc(Dictionaries::getCreatTime);
                    }
                    break;
                default:
                    // 默认按创建时间倒序排序（最新创建的记录在前）
                    queryWrapper.orderByDesc(Dictionaries::getCreatTime);
                    break;
            }
        } else {
            // 默认按创建时间倒序排序（最新创建的记录在前）
            queryWrapper.orderByDesc(Dictionaries::getCreatTime);
        }
        if (DictionaryType.of(type) == null) {
            queryWrapper.eq(Dictionaries::getType, type);
        }
        // 由于泛型类型不匹配，需要进行类型转换
        @SuppressWarnings("unchecked")
        Page<?> sourcePage = ((IService<Dictionaries>) service).page(new Page<>(pageNum, pageSize), queryWrapper);

        // 复制分页信息
        resultPage.setTotal(sourcePage.getTotal());
        resultPage.setPages(sourcePage.getPages());
        resultPage.setCurrent(sourcePage.getCurrent());
        resultPage.setSize(sourcePage.getSize());

        // 直接使用服务返回的记录（子类已继承Dictionaries）
        List<?> records = sourcePage.getRecords();
        // 直接使用Dictionaries类型的分页对象，无需额外类型转换
        List<Dictionaries> collect = records.stream().map(record -> {
            if (record instanceof Dictionaries) {
                return (Dictionaries) record;
            }
            // 若记录不是 Dictionaries 类型，创建一个新的 Dictionaries 对象并复制属性
            Dictionaries newRecord = new Dictionaries();
            BeanUtils.copyProperties(record, newRecord);
            return newRecord;
        }).collect(Collectors.toList());
        resultPage.setRecords(suppleName(collect));
        return R.ok(resultPage);
    }

    /**
     * 补充创建人+修改人+接收人 名称
     * 
     * @param list
     * @return
     */
    private List<Dictionaries> suppleName(List<Dictionaries> list) {
        for (Dictionaries item : list) {
            // 创建人
            User author = userService.getById(item.getUserid());
            if (null != author)
                item.setUsername(author.getName());
            // 更新人
            User modifier = userService.getById(item.getModifier());
            if (null != modifier)
                item.setModifierName(modifier.getName());
        }
        return list;
    }

    /**
     * 新增字典
     */
    @PostMapping("save")
    @MyLogsAOP(operation = OPERATION_DICTIONARIES, operaType = LogType.ADD)
    public R add(@RequestBody DictionariesDTO param) {
        if (param.getType() == null || param.getType().trim().isEmpty()) {
            return R.fail("字典类型(type)不能为空");
        }
        // 获取当前登录用户ID并设置到userid字段
        param.setUserid(Objects.requireNonNull(TokenUtils.getCurrentUser()).getId());
        IService service = getServiceByType(param.getType());

        // 对于定制标准件类型，需要创建DicDz对象以正确处理priority字段
        Object entityToSave = param;
        if (DictionaryType.DZ.code.equals(param.getType())) {
            DicDz dicDz = new DicDz();
            BeanUtils.copyProperties(param, dicDz);
            entityToSave = dicDz;
        }

        boolean save = service.save(entityToSave);
        return save ? R.ok() : R.fail();
    }

    /**
     * 根据字典类型获取对应的服务实例
     * 
     * @param type 字典类型编码（支持dz/cz/gg等）
     * @return 匹配的服务实例，无匹配时返回默认字典服务
     */
    private IService<? extends Dictionaries> getServiceByType(String type) {
        DictionaryType dictType = DictionaryType.of(type);
        if (dictType == null) {
            log.warn("Unsupported or invalid dictionary type: '{}', using default service", type);
            return dictionariesService;
        }
        switch (dictType) {
            case DZ:
                return dicDzService;
            case CZ:
                return dicCzService;
            case GG:
                return dicGgService;
            default:
                return dictionariesService;
        }
    }

    /**
     * 更新字典
     */
    @PutMapping("update/{id}")
    @MyLogsAOP(operation = OPERATION_DICTIONARIES, operaType = LogType.UPDATE)
    public R update(@PathVariable Long id, @RequestBody DictionariesDTO dictionaries) {
        if (dictionaries.getType() == null || dictionaries.getType().trim().isEmpty()) {
            return R.fail("字典类型(type)不能为空");
        }
        dictionaries.setId(id);
        dictionaries.setModifier(Objects.requireNonNull(TokenUtils.getCurrentUser()).getId());
        IService service = getServiceByType(dictionaries.getType());

        // 对于定制标准件类型，需要创建DicDz对象以正确处理priority字段
        Object entityToUpdate = dictionaries;
        if (DictionaryType.DZ.code.equals(dictionaries.getType())) {
            DicDz dicDz = new DicDz();
            BeanUtils.copyProperties(dictionaries, dicDz);
            entityToUpdate = dicDz;
        }

        boolean update = service.updateById(entityToUpdate);
        return update ? R.ok() : R.fail();
    }

    /**
     * 根据ID删除字典
     */
    @DeleteMapping("deleteById/{id}")
    @MyLogsAOP(operation = OPERATION_DICTIONARIES, operaType = LogType.DELETE)
    public R deleteById(@PathVariable Long id, @RequestParam String type) {
        IService service = getServiceByType(type);
        boolean remove = service.removeById(id);
        return remove ? R.ok() : R.fail();
    }

}
